#include <iostream>
#include <cstring>
#include <new>
#include <cstdlib>

using namespace std;

#if 1

/* 运算符重载 */
class R
{
	int n;//分子
	int d;//分母
	friend ostream& operator<<(ostream& o,const R& x);//友元声明，向这个函数授权允许访问本类成员。
	friend istream& operator>>(istream& i,R& x);//x不要加const，用来输入
	friend R operator+(const R& lh,const R& rh);
	public:
	R(int n1,int d1=1):n(n1),d(d1)
	{
		if(d==0)
		{}
		if(d<0)
			n=-n,d=-d;
		for(int i=d;i>1;i--)//约分，笨算法
			if(d%i==0&&n%i==0)
			{
				d/=i,n/=i;
				break;
			}
	}
};

ostream& operator<<(ostream& o,const R& x)
{
	o << x.n << '/' << x.d;
	/*operator<<(o,x.n)==>operator<<(ostream&,int) */
	return o;
}
istream& operator>>(istream& i,R& x)//x不要加const，用来输入
{
	char c;//舍弃'/'
	int n,d;
	i >> n >> c >> d;
	x=R (n,d);//匿名对象。约分
	return i;
}
R operator+(const R& lh,const R& rh)
{
	return R (lh.n*rh.d+lh.d*rh.n,lh.d*rh.d);//匿名对象
}

int main()
{
	R a(6,8),b(8,-12);
	cout << a << ' ' << b << endl;	//operator<<(cout,a)
	cin >> a >> b;//从键盘输入: 6/9 1/3
	cout << a << ' ' << b << endl;
	cout << a+b << endl;//operator<<(cout,operator+(a,b)).operator<<(endl)
	return 0;
}


#else

/****************/
typedef int T;
class Arr
{
	T* a;
	int len;
	mutable int cur;	//const对象内部允许修改的成员
	public:
	Arr(int n,T init=T()):a(new T[n]),len(n),cur(0)	
	{
		for(int i=0;i<n;i++)
			a[i]=init;
		len=n;
	}
	~Arr()
	{
		delete[] a;a=NULL;
	}
	void set(int idx,int val)
	{
		a[idx]=val;
	}
	T get(T idx)
	{
		return a[idx];
	}
	void randfill()
	{
		srand(time(NULL));//设置种子
		for(int i=0;i<len;i++)
			a[i]=rand()%100;//获得100以内的随机数
	}
	int size()
	{
		return len;
	}
	T next()const	//const成员函数，不会修改当前对象的数据
	{
		return a[(cur++)%len];
	}
};

void use(const Arr& x)
{
	for(int i=0;i<3;i++)
		cout << x.next() << ' ';
	cout << endl;
	for(int i=0;i<5;i++)
		cout << x.next() << ' ';
	cout << endl;
	for(int i=0;i<4;i++)
		cout << x.next() << ' ';
	cout << endl;
}

int main()
{
	Arr ax(10);
	ax.randfill();
	for(int i=0;i<ax.size();i++)
		cout << ax.get(i) << ' ';
	cout << endl;
	use(ax);
	return 0;
}

/* 无地址的对象 */
class NA
{
	int n;
	double b;
	public:
	NA()
	{
	}
	NA* operator&()
	{
		return NULL;
	}
};

int main()
{
	NA a;
	cout << &a << endl;//取出地址为0，运算符重载，c++运算符被当成函数
	return 0;
}

/* 拷贝构造 */
typedef int T;

class Arr
{
	T* a;
	int len;
	public:
	Arr(int n,T init=T()):a(new T[n])	
	{
		for(int i=0;i<n;i++)
			a[i]=init;
		len=n;
		cout << "创建数组" << len << "个元素" << init << endl;
	}
	Arr(const Arr& ax)//拷贝构造函数：实参是个Arr类型的旧的对象
	{//ax是下面filter中实参x的引用
		/*a=ax.a;//新对象(ab)的a跟x的a指向同一片内存，注意a是指针
		 *		  出错，下面解决 */
		len=ax.len;
		a=new T[len];
		for(int i=0;i<len;i++)
			a[i]=ax.a[i];
		cout << "创建数组对象" << a << "复制了" << ax.a << endl;
	}
	~Arr()
	{
		cout << "释放数组" << a << endl;
		delete[] a;a=NULL;//释放对象时，顺带把数组释放了
	}
	T& at(int idx)
	{
		if(idx<0||idx>=len)
			throw idx;//以异常方式结束程序
		return a[idx];
	}	
	int size()
	{
		return len;
	}
	void resize(int newsize,const T& val=T())
	{
		if(newsize<=len)
			len=newsize;
		else
		{
			T* np=new T[newsize];
			for(int i=0;i<len;i++)
				np[i]=a[i];
			for(int j=len;j<newsize;j++)
				np[j]=val;
			delete[] a;
			a=np;
			len=newsize;
		}
	}
	void print()
	{
		for(int i=0;i<len;i++)
			cout << a[i] << ' ';
		cout << endl;
	}
	void fill(const T& start,const T& step=T())
	{
		for(int i=0;i<len;i++)
			a[i]=start+step*i;
	}
};

/* 过滤数组中的偶数显示出来，返回原来的数组A */
Arr filter(Arr ab) //注意形参,不是引用
{//filter(x)新建对象ab用x初始化，调用拷贝构造函数A(const A& ax),参数为x
	for(int i=0;i<ab.size();i++)
		if(!(ab.at(i)&1))
			cout << ab.at(i) << ' ';
	cout << endl;
	return ab;//返回，再次复制
}

int main()
{
	Arr x(20);
	x.fill(11,1);
	x.print();

	filter(x).print();
	return 0;
}

/* 数组类，封装和增强数组的功能 */
typedef int T;

class Arr
{//数组类，封装和增强数组的功能
	T* a;
	int len;
	public:
	Arr(int n,T init=T()):a(new T[n])	//T()表示零初始化,对类而言零初始化就是匿名对象。char类型为'\0'，int类型为0
	{
		for(int i=0;i<n;i++)
			a[i]=init;
		len=n;
		cout << "创建数组" << len << "个元素" << init << endl;
	}
	~Arr()
	{
		cout << "释放数组" << a << endl;
		delete[] a;a=NULL;//释放对象时，顺带把数组释放了
	}
	T& at(int idx)
	{
		if(idx<0||idx>=len)
			throw idx;//以异常方式结束程序
		return a[idx];
	}	
	int size()
	{
		return len;
	}
	void resize(int newsize,const T& val=T())
	{
		if(newsize<=len)
			len=newsize;//舍弃一部分空间
		else
		{
			T* np=new T[newsize];
			for(int i=0;i<len;i++)
				np[i]=a[i];
			for(int j=len;j<newsize;j++)
				np[j]=val;
			delete[] a;
			a=np;
			len=newsize;
		}
	}
	void print()
	{
		for(int i=0;i<len;i++)
			cout << a[i] << ' ';
		cout << endl;
	}
	void fill(const T& start,const T& step=T())
	{
		for(int i=0;i<len;i++)
			a[i]=start+step*i;
	}
};

int main()
{
	Arr x(20);
	x.at(3)=5;
	cout << x.size() << endl;
	x.print();

	Arr y(10,6);
	y.print();
	y.resize(15,9);
	y.print();

	x.fill(20,-1);
	y.fill(10,2);
	x.print();
	y.print();
	return 0;
}

/* 析构释放额外的资源 */
class Buffer
{
	string name;
public:
	Buffer(const string& filename):name(filename)
	{
		cout << "为" << filename << "分配缓冲区" << endl;
	}	
	~Buffer()
	{
		cout << "清理" << name << "的缓冲区" << endl;
	}

};

class File
{
	string path;
	Buffer* p;
public:
	File(const string& path="wu ming"):path(path),p(0)
	{
		cout << this << " touch file " << path << endl;
	}
	~File()//析构，对象释放时自动调用
	{
		cout << this << path << "释放" << endl;
		close();
	}
	void open()
	{
		p=new Buffer(path);//动态分配缓冲区资源
	}
	void close()
	{
		delete p;p=NULL;//释放缓冲区资源
	}
};

int main()
{
	File a("a");
	File* p2=new File("~/p2");

	a.open();
	p2->open();
	delete p2;p2=NULL;

	return 0;
}

/* 匿名对象 */
class R		//分数类（分子，分母）
{
	int n;
	int d;//fen mu
	void reduction()	//约分
	{
		int ys=yue(n,d);
		n=n/ys;
		d=d/ys;
	}
	int yue(int a1,int a2)
	{
		if(a1<a2)
		{
			int temp=a1;a1=a2;a2=temp;
		}
		if(!(a1%a2))
			return a2;
		else
		{
			int y=a1%a2;
			a1=a2;a2=y;
			yue(a1,a2);
		}
	}
	public:
	R(int n,int d=1):n(n),d(d)
	{//如果R前加上explicit修饰，就可以禁止本构造函数用于自动类型转换
		cout << "R(" << n << '/' << d << ")" << endl;
	}
	~R()
	{
		cout << "~(" << n << '/' << d << ")" << endl;
	}
	R add(const R& r2)
	{
		int nd=d*r2.d;
		int nn=d*r2.n+n*r2.d;
		/*R result(nn,nd);
		 *		 return result;或 */
		return R (nn,nd);	//匿名对象
	}
	void show()
	{
		reduction();
		cout << n << '/' << d << endl;
	}
};

int main()
{
	R a(2,5),b(3,8);
	a.add(b).show();
	cout << endl;
	b.add(R(1,6)).show();
	cout << endl;
	a.add(R(3));
	cout << endl;
	a.add(3);//通过匿名对象做自动类型转换R(3)
	return 0;
}

/* 带构造函数 */
class Person
{
	static int thisyear;//静态成员,这种成员的初始化不应该在构造函数中初始化。
	string name;
	int year;//出生日期
	bool gender;
	Person* lover;
	public:
	Person()	//当添加有参构造函数时，要加上无参构造函数。
	{
		cout << "error!" << endl;
		exit(0);
	}
	Person(const string& name,bool gender)
	{
		Person::name=name;
		year=thisyear;
		this->gender=gender;
		lover=NULL;
	}
	void show()
	{
		cout << "a " << (gender?"boy":"girl") 
			<< ".name is " << name << ".age is " 
			<< thisyear -year << '.';
		if(lover)
			cout << "I love " << lover->name << endl;
		else
			cout << "single!" << endl;
	}
	void love(Person& x)
	{//Person* const this 接受隐含参数，指向当前对象
		lover=&x;
		x.lover=this;
	}
	void fenshou()
	{
		lover->lover=NULL;
		lover=NULL;
	}
	static void timefly(int y)//静态成员函数，对所有对象
	{
		thisyear=y;
	}
};

int Person::thisyear=1900;//函数外面可以初始化，不允许赋值。

int main()
{
	Person::timefly(1990);
	Person A("li",true);
	Person::timefly(1992);
	Person B("wang",false);
	Person::timefly(2014);
	A.show();	//=A.show(&A),传递隐含参数
	B.show();

	A.love(B);
	A.show();
	B.show();

	A.fenshou();
	A.show();
	B.show();
	return 0;
}

/* new */
class File
{
	string path;
	public:
	File(const string& path="wu ming"):path(path)
	{//第一个path是成员，第二个是形参,形参指定默认值，可以不用传参数
		cout << this << " create file " << path << endl;
	}
	~File()//析构，对象释放时自动调用
	{
		cout << this << " " << path << " release file " << endl;
	}
};

int main()
{
	File* p1=new File;
	File* p2=new File("~/p2");
	File* p3=new File[3];
	delete[] p3;p3=NULL;
	delete p1;p1=NULL;
	delete p2;p2=NULL;

	File a("a");//不需要delete，自动释放
	return 0;
}

/* 单例，只能有一个实例 */
class ChairMan
{
	ChairMan(string name):name(name)	
	{}			//构造函数，访问权限私有,初始化列表,成员(形参)
	public:
	const string name;
	static ChairMan& getInstance()	//引用,返回对象本身，而不是复制//静态成员
	{
		static ChairMan cm("xi zhu xi");//静态局部变量
		return cm;
	}
	void show()
	{
		cout << "hello everyone!I'm " << name << endl; 
	}
};

int main()
{
	ChairMan& c=ChairMan::getInstance();
	c.show();

	return 0;
}

/* 构造函数重载 */
class Cat
{
	public:
		Cat()
		{
			cout << "call Cat()" << endl;
		}
		Cat(string str)
		{
			cout << str << endl;
		}
};

int main()
{
	Cat c;//自动调用无参构造函数

	Cat c1("加菲猫");//自动调用带string参数的构造函数

	Cat c2();//Cat类型的函数声明

	return 0;
}

/* 引用 */
void swap(int& p,int& q);
int& counter();

int main()
{
	int a=10,b=20,c=30,d=40;
	cout << "&a=" << &a << ",&b=" << &b << endl;
	swap(a,b);
	cout << "a=" << a << endl << "b=" << b << endl;

	cout << "&c=" << &c << ",&d=" << &d << endl;
	swap(c,d);
	cout << "c=" << c << endl << "d=" << d << endl;

	cout << counter() <<' ';
	cout << counter() <<' ';
	cout << counter() <<endl;
	counter()=0;
	cout << counter() <<' ';
	cout << counter() <<endl;
	return 0;
}

void swap(int& p,int& q)	//传引用
{
	cout << "&p=" << &p << ",&q=" << &q << endl;
	int t=p;
	p=q;
	q=t;
}

int& counter()//计数器，并且可以复位
{
	static int cnt=0;//静态局部变量
	++cnt;
	return cnt;
}

/* 成员指针 */
struct Date
{
	int year;
	int month;
	int day;
	void print()
	{
		cout << year << '-' << month << '-' << day << ' ';
	}
};

void sort(Date a[],int n,int Date::*p)
{
	for(int i=0;i<n;i++)
		for(int j=i+1;j<n;j++)
			if(a[i].*p>a[j].*p)
				swap(a[i],a[j]);
}

int main()
{
	int Date::*p=&Date::year;
	Date a={2013,5,16},b={2014,3,1};
	cout << a.*p << ' ' << b.*p <<endl;
	p=&Date::day;
	cout << a.*p << ' ' << b.*p <<endl;


	Date x[4]={a,b,{1990,8,7},{1999,12,12}};
	sort(x,4,&Date::year);
	for(int i=0;i<4;i++)
		x[i].print();
	cout << endl;

	sort(x,4,&Date::month);
	for(int i=0;i<4;i++)
		x[i].print();
	cout << endl;
	return 0;
}

/* 动态内存 */
int main()
{
	int* pi=new int;

	int n=200;
	char* pc=new char[n];
	double* pd=new double[0xF0];
	long* pl=new long(123);//指定初始值
	short* ps=new short();//? 

	*pi=12;
	strcpy(pc,"hello");
	pd[10]=12.32;

	cout << *pi << ' ' << pc << ' ' << pd[10] << 
		' ' << *pl << ' ' <<  *ps << endl;

	delete pi;
	delete[] pc;
	delete[] pd;
	delete pl;
	delete ps;

	double* pdm=new(nothrow)double[0xff];//失败不抛出异常，而返回一个空
	if(pdm!=NULL)
		pdm[0]=12.1;
	if(pd)
		cout << pdm[0] << endl;
	return 0;
}

/* 形参默认值 */
void show(const char* name,char gender='M');

int main()
{
	show("xiaoming");
	show("xiaoli",'F');
	show("fengjie",'N');

	return 0;
}

void show(const char* name,char gender)
{
	cout << name << " " << (gender=='M'?"boy":gender=='F' ? "girl" : "wxr") << endl;
}

/* first class */
struct sDate
{
	int year;
	int month;
	int day;
	void set(int y,int m,int d);
	void print();
};

class cDate		
{
	int year;
	int month;
	int day;
	public: 
	void set(int y,int m,int d);
	void print();
};

/*结构中的成员函数*/
void sDate::set(int y,int m,int d)//函数名前加限定
{
	year=y;month=d;day=d;
}
void sDate::print()
{
	cout << year << '-' << month << '-' << day << endl;
}

/*类中的成员函数*/
void cDate::set(int y,int m,int d)
{
	year=y;month=d;day=d;
}
void cDate::print()
{
	cout << year << '-' << month << '-' << day << endl;
}

int main()
{
	sDate s;
	cDate c;
	c.set(2013,12,11);
	c.print();
	s.set(2012,12,21);
	s.print();
	return 0;
}
/* 函数重载 */
void show(int n)
{
	cout << "int:" << n << endl;
}

void show(double d)
{
	cout << "double:" << d << endl;
}

struct Person
{
	char name[20];
	char gender;
};

void show(Person p)
{
	cout << "one " << (p.gender=='M'?"man":p.gender=='F'?"women":"error") 
		<< " people,name " << p.name << endl;
}

int main()
{
	show(2);
	show(2.3);
	Person xm={"xiaoming",'N'};
	show(xm);
	return 0;
}

/* 类型转换 */
int main()
{
	int a=static_cast<int>(12.32);
	cout << "a=" << a << endl;
	int b=100;
	/*...*/
	void* p=&b;
	int* q=static_cast<int*>(p);
	cout << "b=" << b << endl;

	char* r=reinterpret_cast<char*>(q);
	cout << "*r=" << *r << endl;

	const int c=b;
	cout << "c=" << c << endl;

	*const_cast<int*>(&c)=200;
	cout << "c=" << c << endl;

	return 0;

	//volatile //不稳的变量
}

/* namespace, struct, union exercise */
namespace A{
	struct Student
	{
		char name[20];
		int age;
		void show()
		{
			cout << age << "years old," << name << "learn C++ easily" << endl;
		}
	};
}

int main()
{
	A::Student student1={"xiaoming",18};

	using namespace A;
	Student student2;
	strcpy(student2.name,"xiaowang");
	student2.age=20;

	student1.show();
	student2.show();

	union
	{
		int x;
		char y[4];	
	};	//匿名联合
	x=0x61626364;
	cout << y[0] << endl;
	y[1] = '0';	//0x30
	cout << hex << showbase << x << endl;//hex是按16进制输出,showbase前缀
	return 0;
}

/* first c++ program */
int main()
{
	std::cout << "Hello World!" << std::endl;

	std::cout << "please input your name: ";
	char name[20];
	std::cin >> name;
	std::cout << name << std::endl;

	return 0;
}
#endif //main
